home *** CD-ROM | disk | FTP | other *** search
/ PC World 2008 September / PCWorld_2008-09_cd.bin / v cisle / sadanastroju / delicious_bookmarks-2.0.64-fx.xpi / chrome / deliciousBookmarks.jar / content / yAddBookMark.js < prev    next >
Encoding:
Text File  |  2008-06-19  |  63.0 KB  |  1,655 lines

  1. const YB_ADDBOOKMARK_NOTES_MAX_LENGTH = 255;
  2. const YB_ADDBOOKMARK_TITLE_MAX_LENGTH = 255;
  3. var yAddBookMark = {
  4.    post: {
  5.       title: '',
  6.       url: '',
  7.       tags: null,
  8.       systemTags: null,
  9.       notes: '',
  10.       shared: "true",
  11.       rss: false,
  12.       shortcut: "",
  13.       postData: "",
  14.       added_date: null
  15.    },
  16.    config: {
  17.       maxSuggestedTags: 8,
  18.       midColMaxChars: null,
  19.       inputTagBoxID: 'tb_ybTags',
  20.       traditionalAddPref: 2,
  21.       rssTag: 'firefox:rss',
  22.       emptyTag: 'system:unfiled',
  23.       dialogID: 'dlg_AddYBookMark',
  24.       specialTagPref: 'system:',
  25.       shortcutTagPref: 'shortcut:',
  26.       attr_selected: "yb_selected",
  27.       attr_related: "yb_related",
  28.       sgstTagPrefix: "lbl_sgstTag_",
  29.       class_mousedOver: "moused-over-tag",
  30.       class_mousedOut: "moused-out-tag",
  31.       bmLetURLPref: "javascript:"
  32.    },
  33.    inputTagBox: null,
  34.    editOp: false,
  35.    blankEntry: false,
  36.    keywordInput: false,
  37.    existingEntry: null,
  38.    kDelContractID: "@yahoo.com/socialstore/delicious;1",
  39.    kLocalStoreContractID: "@mozilla.org/ybookmarks-store-service;1",
  40.    kSyncServiceContractID: "@mozilla.org/ybookmarks-sync-service;1",
  41.    nSgstTagInserts: 0,
  42.    nameInputElt: null,
  43.  
  44.    localStore: null,
  45.    syncService: null,
  46.  
  47.    _bookmarkID: null,
  48.    _microsummaries: null,
  49.    __mss: null,
  50.    originalGetShortcutOrURI: null,
  51.  
  52.    get _mss() {
  53.      if (!this.__mss) {
  54.        this.__mss = Components.classes["@mozilla.org/microsummary/service;1"];
  55.        if (this.__mss) {
  56.          this.__mss = this.__mss.getService( Components.interfaces.nsIMicrosummaryService );
  57.        }
  58.      }
  59.      return this.__mss;
  60.    },
  61.  
  62.  
  63.    __ios: null,
  64.    get _ios() {
  65.      if (!this.__ios)
  66.        this.__ios = Components.classes["@mozilla.org/network/io-service;1"].
  67.                    getService(Components.interfaces.nsIIOService);
  68.        return this.__ios;
  69.    },
  70.  
  71.    _prefs: null,
  72.    get prefs() {
  73.       if( this._prefs == null ) {
  74.          this._prefs = Components.classes["@mozilla.org/preferences-service;1"].
  75.                               getService(Components.interfaces.nsIPrefBranch);
  76.       }
  77.       return this._prefs;
  78.    },
  79.  
  80.    open: function( url, title, charset, isWebPanel, notes, feedUrl, blankEntry, postData, keywordInput, userSelectedTag ) {
  81.       // check if user is logged in
  82.       if( !YBidManager.isUserLoggedIn() ) {
  83.          YBidManager.promptUserLogin();
  84.          
  85.           try {
  86.               if (window.ybLoginWindowFlag == "display") {
  87.                  YBPopupWindow.showLoginWindow();
  88.               }
  89.            } catch(e) {
  90.                 // do nothing
  91.            }
  92.          
  93.          return;
  94.       }
  95.  
  96.       if( url == null ) {
  97.          url = '';
  98.       }
  99.       if( title == null ) {
  100.          title = '';
  101.       }
  102.       if( blankEntry == null ) {
  103.          blankEntry = false;
  104.       }
  105.       if( keywordInput == null ) {
  106.          keywordInput = false;
  107.       }
  108.  
  109.       this.post.url = url;
  110.       this.post.title = title;
  111.       this.post.notes = (notes?notes:'');
  112.       this.post.charset = (charset?charset:"");
  113.       this.post.isWebPanel = (isWebPanel?isWebPanel:false);
  114.       this.post.tags = new Array();
  115.       this.post.shortcut = "";
  116.       this.post.systemTags = null;
  117.  
  118.       if( postData != null ) {
  119.          this.post.postData = postData;
  120.       }
  121.       else {
  122.          this.post.postData = "";
  123.       }
  124.  
  125.       if (feedUrl) {
  126.         this.post.url = feedUrl;
  127.         this.post.rss = true;
  128.       } else {
  129.         this.post.rss = false;
  130.       }
  131.  
  132.       if( ( this.post.url.length == 0 ) && ( blankEntry != true ) ) {
  133.          this._getDoc( window );
  134.       }
  135.  
  136.       var defaultSharing = 0;
  137.       try {
  138.         defaultSharing = this.prefs.getIntPref( "extensions.ybookmarks@yahoo.sharemode" );
  139.         // 1 - private  2 - public
  140.         defaultSharing = ( defaultSharing == 1 ? "false" : "true" );
  141.       } catch ( e ) {
  142.         defaultSharing = "true";
  143.       }
  144.  
  145.       this.post.shared = defaultSharing;
  146.  
  147.       if( blankEntry != true ) {
  148.          this._checkForEditOperation();
  149.       }
  150.       //handle classic mode
  151.       if( (this._checkAddMechPref() == this.config.traditionalAddPref) || (ybookmarksUtils.getExtensionMode() == YB_EXTENSION_MODE_CLASSIC)) {
  152.          this._traditionalAdd();
  153.       }
  154.       else {
  155.          var rv = { openTraditionalAdd: false };
  156.          
  157.          window.openDialog( "chrome://ybookmarks/content/yAddBookMark.xul",
  158.                             "AddBookMarks",
  159.                             "chrome,dialog,centerscreen,resizable=no", 
  160.                             this.post, this.editOp, blankEntry, keywordInput, rv, userSelectedTag );
  161.       }
  162.    },
  163.  
  164.    _getLocalStore: function() {
  165.       if( this.localStore == null ) {
  166.          try {
  167.             this.localStore = ( Components.classes[ this.kLocalStoreContractID ].
  168.                                 getService( Components.interfaces.nsIYBookmarksStoreService ) );
  169.          }
  170.          catch( e ) {
  171.             yDebug.print( "couldn't get ystore!", YB_LOG_MESSAGE );
  172.             return;
  173.          }
  174.       }
  175.    },
  176.  
  177.    _getSyncService: function() {
  178.       if( this.syncService == null ) {
  179.          try {
  180.             this.syncService = ( Components.classes[this.kSyncServiceContractID].
  181.                                  getService(Components.interfaces.nsIYBookmarkSyncService) );
  182.          }
  183.          catch( e ) {
  184.             yDebug.print( "couldn't get syncService!", YB_LOG_MESSAGE );
  185.             return;
  186.          }
  187.       }
  188.    },
  189.  
  190.    _checkForEditOperation: function() {
  191.       this._getLocalStore();
  192.       var bookmarkResource = this.localStore.isBookmarked( this.post.url );
  193.       yDebug.print ( "Existing entry for " + this.post.url + " => " + bookmarkResource );
  194.       if( bookmarkResource == null ) {
  195.          this.editOp = false;
  196.       }
  197.       else {
  198.          // check if the bookmark is a child of livemark. Bookmark object within Livemark is not
  199.          // eligible for edit operations.
  200.          var bookmarkType = this.localStore.resolveBookmarkResourceType( bookmarkResource );
  201.          if ( bookmarkType == "LiveBookmark" ) {
  202.            this.editOp = false;
  203.          } else {
  204.            this.editOp = true;
  205.            this.existingEntry = this.localStore.getBookmark( this.post.url );
  206.  
  207.            // see if microsummary was used while editing. If keep the title same as 
  208.            // that of the web page
  209.            var microSummaries = null;
  210.            if (this._mss ) {
  211.              try { // 2007-01-11 cmyang: need this try/catch block because the mss barfs on non HTML/XML (i.e images, etc)
  212.              microSummaries = this._mss.getMicrosummaries( this._ios.newURI ( this.post.url, null, null ),
  213.                                                                this.localStore.isBookmarked( this.post.url )
  214.                                                              );
  215.              } catch(e) {
  216.                yDebug.print("Microsummary Service error with URL '" + this.post.url + "': " + e + " --> Ignoring Error");
  217.              }
  218.            }
  219.            if ( !microSummaries || !microSummaries.Enumerate().hasMoreElements() ) {
  220.              this.post.title = this.existingEntry.name;
  221.            }
  222.            this.post.notes = this.existingEntry.description;
  223.            this.post.shared = this.existingEntry.shared;
  224.            this.post.localOnly = this.existingEntry.localOnly;           
  225.            this.post.shortcut = this.existingEntry.shortcut;
  226.            this.post.postData = this.existingEntry.postData;
  227.            this.post.added_date = this.existingEntry.added_date;
  228.            
  229.            //todo: load shared attribute here
  230.  
  231.            yDebug.print( "name: " + this.existingEntry.name );
  232.            yDebug.print( "url: " + this.existingEntry.url );
  233.            yDebug.print( "description: " + this.existingEntry.description );
  234.            yDebug.print( "Shared: " + this.existingEntry.shared );
  235.            yDebug.print( "localOnly: " + this.existingEntry.localOnly );
  236.            yDebug.print( "postData: " + this.existingEntry.postData );
  237.            yDebug.print( "added_date: " + this.existingEntry.added_date );
  238.  
  239.            var tag, tags = this.existingEntry.tags.enumerate();
  240.            while( tags.hasMoreElements() ) {
  241.               tag = 
  242.                  ( tags.getNext().QueryInterface( Components.interfaces.nsISupportsString ) ).data;
  243.               this.post.tags.push( tag );
  244.            }
  245.          }
  246.       }
  247.    },
  248.    
  249.    urlClick: function() {
  250.         var txtbx = document.getElementById( 'tb_yBookmarkURL' );
  251.         var lbl = document.getElementById( 'lbl_yBookmarkURL' );
  252.         lbl.hidden = true;
  253.         txtbx.hidden = false;
  254.         txtbox.focus();
  255.     },
  256.  
  257.    init: function() {
  258.  
  259.       try {
  260.          this.post = window.arguments[ 0 ];
  261.          this.editOp = window.arguments[ 1 ];
  262.          this.blankEntry = window.arguments[ 2 ];
  263.          this.keywordInput = window.arguments[ 3 ];
  264.          this.userSelectedTag = window.arguments[ 5 ];
  265.       } catch( e ) { }
  266.  
  267.       var elt;
  268.  
  269.       var txtbx = document.getElementById( 'tb_yBookmarkURL' );
  270.       var lbl = document.getElementById( 'lbl_yBookmarkURL' );
  271.       var btn_delete = document.getElementById( 'btn_delete' );
  272.       
  273.       this.strings = document.getElementById("ybookmarks-strings");
  274.       this.config.midColMaxChars = 
  275.          ( document.getElementById( "tb_yBookmarkURL" ) ).getAttribute( "cols" );
  276.       
  277.       if( this.post.url.length > ( this.config.midColMaxChars - 3 ) ) {
  278.          lbl.value = this.post.url.substr( 0, this.config.midColMaxChars - 3 );
  279.          lbl.value += "...";
  280.       }
  281.       else {
  282.          lbl.value = this.post.url;
  283.       }
  284.       txtbx.value = this.post.url;
  285.  
  286.       if( this.editOp || ( this.blankEntry == true ) || ( this.keywordInput == true ) ) {
  287.          document.getElementById( "rw_keywordInput" ).hidden = false;
  288.       }
  289.       else {
  290.          ( document.getElementById( "tb_yBookmarkKeyword" ) ).setAttribute( "tabindex", "-1" );
  291.       }
  292.       
  293.       if( this.editOp || ( this.blankEntry == true ) ) {
  294.          lbl.hidden = true;
  295.          txtbx.focus();
  296.          btn_delete.hidden = false;
  297.       }
  298.       else {
  299.          lbl.hidden = false;
  300.          lbl.setAttribute( "class", this.config.class_mousedOut );
  301.          lbl.setAttribute( "onclick", "yAddBookMark.urlClick();" );
  302.          txtbx.hidden = true;
  303.          txtbx.setAttribute( "tabindex", "-1" );
  304.          ( document.getElementById( "tb_yBookmarkName" ) ).focus();
  305.          btn_delete.hidden = true;
  306.       }
  307.  
  308.       document.getElementById( 'tb_yBookmarkName' ).value = this.post.title;
  309.       document.getElementById( 'menu_yBookmarkName' ).value = this.post.title;
  310.       document.getElementById( "userEnteredNameItem").label = this.post.title;
  311.       this.nameInputElt = 'tb_yBookmarkName';
  312.  
  313.       document.getElementById('tb_yBookmarkNotes').setAttribute("oninput", "yAddBookMark.updateNotesCount();");
  314.       
  315.       this.inputTagBox = document.getElementById( this.config.inputTagBoxID );
  316.       
  317.       /**
  318.        * Hack to hide value column and add color
  319.        
  320.      this.inputTagBox.popup.treecols.firstChild.hidden = "true";
  321.      this.inputTagBox.popup.tree.childNodes[1].style.color = "blue";
  322.      */
  323.      
  324.       if( this.post.notes.length > 0 ) {
  325.          elt = document.getElementById( 'tb_yBookmarkNotes' );
  326.          elt.value = this.post.notes;
  327.       }
  328.  
  329.       if ( this.post.tags ) {
  330.          for( var i = 0; i < this.post.tags.length; ++i ) {
  331.             // hide the implicit tags
  332.             if( !this._isSystemTag( this.post.tags[ i ] ) ) {
  333.                yDebug.print( "going to add " + this.post.tags[ i ] );
  334.                this._addToUserTags( this.post.tags[ i ] );
  335.             } 
  336.             else { 
  337.                   if( !this.post.systemTags ) {
  338.                      this.post.systemTags = new Array();
  339.                   }
  340.                   this.post.systemTags.push( this.post.tags[i] );
  341.             }
  342.          }
  343.       }
  344.       
  345.       if(this.userSelectedTag && (this.post.tags.indexOf(this.userSelectedTag) == -1)) {
  346.           this._addToUserTags( this.userSelectedTag );
  347.       }
  348.       
  349.       if( this.editOp == true ) {
  350.          document.title = 
  351.             document.getElementById( this.config.dialogID ).getAttribute( "editTitle" );
  352.          document.getElementById('img_dlgTitle').setAttribute( "src", "chrome://ybookmarks/skin/deliciousEditBookmark.gif" );
  353.       }
  354.       else {
  355.          document.title = 
  356.             document.getElementById( this.config.dialogID ).getAttribute( "addTitle" );
  357.          document.getElementById('img_dlgTitle').setAttribute( "src", "chrome://ybookmarks/skin/deliciousSaveaBookmark.gif" );            
  358.       }
  359.  
  360.       var noShareCheckbox = document.getElementById( "cb_noShare" );
  361.       if (this.post.shared && this.post.shared == "false") {
  362.         noShareCheckbox.checked = true;
  363.       }   
  364.       
  365.       var showLocalOnlyOption;
  366.       try {
  367.         showLocalOnlyOption = this.prefs.getBoolPref("extensions.ybookmarks@yahoo.show.localonly.option");
  368.       } catch(e) {
  369.         showLocalOnlyOption = false;
  370.       }
  371.         
  372.       if (showLocalOnlyOption) {
  373.         var localOnlyCheckbox = document.getElementById("cb_localOnly");
  374.         localOnlyCheckbox.hidden = false;
  375.         if (this.post.localOnly && this.post.localOnly == "true") {
  376.           localOnlyCheckbox.checked = true;
  377.           noShareCheckbox.checked = true;
  378.           noShareCheckbox.disabled = true;
  379.         }
  380.       }
  381.         
  382.       document.getElementById( "tb_yBookmarkKeyword" ).value = this.post.shortcut;
  383.  
  384.       if( this.post.url.substr( 0, this.config.bmLetURLPref.length ) ==  this.config.bmLetURLPref ) {
  385.         noShareCheckbox.checked = true;
  386.         noShareCheckbox.disabled = true;
  387.       }
  388.       else if( this.post.url != '' ) {
  389.         this._querySuggestedTags();
  390.       }
  391.       
  392.       var lbl_origPostInfo = document.getElementById( "lbl_origPostInfo" );
  393.       if( this.editOp == true ) {
  394.           var added_date = new Date(this.post.added_date / 1000);
  395.           yDebug.print("*** added_date = " + added_date);
  396.           lbl_origPostInfo.value = 
  397.               this.strings.getFormattedString("extensions.ybookmarks.edit_dialog.originally_posted_on", 
  398.                                               [
  399.                                                added_date.getFullYear(), 
  400.                                                added_date.getMonth() + 1,
  401.                                                added_date.getDate(),
  402.                                                added_date.getHours(),
  403.                                                added_date.getMinutes()
  404.                                                ]);
  405.           lbl_origPostInfo.hidden = false;
  406.       } else {
  407.           lbl_origPostInfo.hidden = true;
  408.       }
  409.  
  410.       try {
  411.          this._initMicrosummary();
  412.       }
  413.       catch( e ) {
  414.          yDebug.print( "exception while executing  _initMicrosummary: " + e, YB_LOG_MESSAGE );
  415.       }
  416.  
  417.       this._resetSaveButton();
  418.  
  419.       document.getElementById( "lbl_userName" ).setAttribute( 
  420.          "value", deliciousService.getUserName() );
  421.  
  422.       if( this.post.notes.length == 0 ) {
  423.          var wm = Components.classes[ "@mozilla.org/appshell/window-mediator;1" ]
  424.                                .getService( Components.interfaces.nsIWindowMediator );
  425.          var browserWin = wm.getMostRecentWindow( "navigator:browser" );
  426.          var selObj = browserWin.content.getSelection();
  427.          if( selObj ) {
  428.             var str = selObj.toString();
  429.             if( str && str.length > 0 ) {
  430.                ( document.getElementById( "tb_yBookmarkNotes" ) ).setAttribute( "value", str );
  431.             }
  432.          }
  433.       }
  434.  
  435.       /*
  436.       elt = document.getElementById( "lbl_popTagsHelp" );
  437.       elt.setAttribute( "value", elt.getAttribute( "value" ) + deliciousService.getServiceName() );
  438.       */
  439.       this.updateNotesCount();
  440.       //Set focus on the tags field.
  441.       ( document.getElementById( "tb_ybTags" ) ).focus();
  442.    },
  443.    
  444.    uninit : function() {
  445.    },
  446.    
  447.    _isSystemTag: function( tag ) {
  448.       if( tag.substr( 0, this.config.specialTagPref.length ) == this.config.specialTagPref ) {
  449.          return true;
  450.       }
  451.       if( tag.substr( 0, this.config.shortcutTagPref.length ) == this.config.shortcutTagPref ) {
  452.          return true;
  453.       }
  454.       if( tag == this.config.rssTag ) {
  455.          return true;
  456.       }
  457.       return false;
  458.    },
  459.  
  460.    _initMicrosummary: function() {
  461.      if (!this._mss) {
  462.        yDebug.print ( "Microsummary is not available in this version of firefox. Please upgrade to Firefox 2.x" );
  463.        document.getElementById( "menu_yBookmarkName" ).setAttribute( "droppable", "false" );
  464.        return;
  465.      }
  466.  
  467.      if ( this.post.url.length <= 0 ) {
  468.         yDebug.print ( "Nothing to bookmark here" );
  469.         document.getElementById( "menu_yBookmarkName" ).setAttribute( "droppable", "false" );
  470.         return;
  471.      }
  472.  
  473.      this._getLocalStore();
  474.      this._bookmarkID = this.localStore.isBookmarked( this.post.url );
  475.      var uri = this._ios.newURI ( this.post.url, null, null );
  476.      this._microsummaries = this._mss.getMicrosummaries( uri,
  477.                                                          this._bookmarkID
  478.                                                        );
  479.      this._observer._self = this;
  480.      this._microsummaries.addObserver(this._observer);
  481.      this.updateMicrosummary();
  482.    },
  483.  
  484.    _observer: {
  485.  
  486.       interfaces: [ Components.interfaces.nsIMicorsummaryObserver, Components.interfaces.nsISupports ],
  487.  
  488.       onContentLoaded: function(microsummary) {
  489.         this._self.updateMicrosummary();
  490.       },
  491.  
  492.       onElementAppended: function(microsummary) {
  493.         this._self.updateMicrosummary();
  494.       }
  495.    },
  496.  
  497.    onInput: function( elt ) {
  498.       if( elt.id == "menu_yBookmarkName" ) {
  499.          var nameField = document.getElementById( "menu_yBookmarkName" );
  500.          var nameItem = document.getElementById( "userEnteredNameItem" );
  501.          nameItem.label = nameField.value;
  502.       }
  503.       this._resetSaveButton();
  504.       // check if bookmarklet is being changed
  505.       if( ( this.editOp ) && ( elt.id == "tb_yBookmarkURL" ) ) {
  506.          var urlField = document.getElementById( "tb_yBookmarkURL" );
  507.          var cb = document.getElementById( "cb_noShare" );
  508.          if( urlField.value.substr( 0, this.config.bmLetURLPref.length ) == this.config.bmLetURLPref ) {
  509.             cb.checked = true;
  510.             cb.disabled = true;
  511.          }
  512.          else {
  513.             cb.disabled = false;
  514.          }
  515.       }
  516.    },
  517.    
  518.    updateNotesCount:function() {
  519.      try {
  520.        
  521.        var notesInput = document.getElementById("tb_yBookmarkNotes");
  522.        /*if (notesInput.textLength > YB_ADDBOOKMARK_NOTES_MAX_LENGTH) {
  523.          notesInput.value = notesInput.value.substring(0, YB_ADDBOOKMARK_NOTES_MAX_LENGTH);
  524.        }*/
  525.     
  526.        var notesCount = document.getElementById("lbl_notesCount");
  527.        var charsRemaining = YB_ADDBOOKMARK_NOTES_MAX_LENGTH - notesInput.textLength;
  528.        var numString = yAddBookMark.strings.getFormattedString("extensions.ybookmarks.edit_dialog.name.count", 
  529.                                                         [ charsRemaining ]);
  530.        notesCount.value = numString;
  531.        if (charsRemaining < 0) {
  532.          notesCount.setAttribute("class", "overflowed")
  533.        } else {
  534.          notesCount.setAttribute("class", "")     
  535.        }
  536.      } catch (e) { 
  537.        yDebug.print("updateNotesCount(): " + e);
  538.      }
  539.    },
  540.  
  541.    onSelectLocalOnlyOption : function(event) {
  542.      
  543.      var noShareCheckbox = document.getElementById( "cb_noShare" );
  544.      if (event.target.checked) {
  545.        noShareCheckbox.checked = true;
  546.        noShareCheckbox.disabled = true;
  547.      }
  548.      else {
  549.        if ( this.post.url.substr( 0, this.config.bmLetURLPref.length ) ==  this.config.bmLetURLPref ) {
  550.          noShareCheckbox.checked = true;
  551.          noShareCheckbox.disabled = true;
  552.        }
  553.        else {
  554.          noShareCheckbox.disabled = false;
  555.        }  
  556.      }
  557.    },
  558.  
  559.    _resetSaveButton: function() {
  560.       var okButton = document.getElementById( "btn_save" );
  561.       var nameField = document.getElementById( this.nameInputElt );
  562.       var urlField = document.getElementById( "tb_yBookmarkURL" );
  563.       okButton.disabled = 
  564.          ( nameField.value.length == 0 || urlField.value.length == 0 ) ? true : false;
  565.    },
  566.          
  567.    updateMicrosummary: function() {
  568.      if (!this._microsummaries)
  569.        return;
  570.  
  571.      var summaryList = document.getElementById( "menu_yBookmarkName" );
  572.      var microsummaryPopup = document.getElementById( "microsummaryMenuPopup" );
  573.  
  574.      while ( microsummaryPopup.childNodes.length > 2 ) {
  575.         microsummaryPopup.removeChild ( microsummaryPopup.lastChild );
  576.      }
  577.  
  578.      var enumerator = this._microsummaries.Enumerate();
  579.      if ( enumerator.hasMoreElements() ) {
  580.         summaryList.setAttribute( "droppable", "true" ); 
  581.      } else {
  582.         summaryList.setAttribute( "droppable", "false" ); 
  583.      }
  584.  
  585.      var activeMicrosummary = null;
  586.      if ( summaryList.menuBoxObject.activeChild ) {
  587.        activeMicrosummary = summaryList.menuBoxObject.activeChild.microsummary;
  588.      }
  589.  
  590.      var nInserts = 0;
  591.      while ( enumerator.hasMoreElements() ) {
  592.        var microsummary = enumerator.getNext().QueryInterface ( Components.interfaces.nsIMicrosummary );
  593.        if ( microsummary.content ) {
  594.          var menuitem = document.createElement ( "menuitem" );
  595.          menuitem.setAttribute( "label", microsummary.content );
  596.          // for commit use
  597.          menuitem.microsummary = microsummary;
  598.          microsummaryPopup.appendChild ( menuitem );
  599.          ++nInserts;
  600.  
  601.          // select the menu item, if this microsummary is the one used while bookmarking earlier
  602.          if ( this._bookmarkID && this._mss.isMicrosummary( this._bookmarkID, microsummary ) ) {
  603.            summaryList.selectedItem = menuitem;
  604.          }
  605.  
  606.          if ( activeMicrosummary && microsummary == activeMicrosummary ) {
  607.            summaryList.menuBoxObject.activeChild = menuitem;
  608.          }
  609.        } else {
  610.          microsummary.update();
  611.        }
  612.      }
  613.      if( ( nInserts > 0 ) && ( this.nameInputElt == "tb_yBookmarkName" ) ) {
  614.        // hide the simple text box and show the menupopup
  615.        var elt = document.getElementById( "tb_yBookmarkName" );
  616.        elt.hidden = true;
  617.        elt.setAttribute( "tabindex", "-1" );
  618.        elt = document.getElementById( "menu_yBookmarkName" );
  619.        elt.hidden = false;
  620.        this.nameInputElt = "menu_yBookmarkName";
  621.        document.getElementById("lbl_nameCount").hidden = true;
  622.        sizeToContent();
  623.        if( !this.editOp ) {                 // URL textbox retains focus in edit dialog
  624.          elt.focus();
  625.        }
  626.      }
  627.    },
  628.  
  629.    _getDoc: function( currWindow ) {
  630.       var browser = currWindow.getBrowser();
  631.       var webNav = browser.webNavigation;
  632.       if( webNav.currentURI ) {
  633.          this.post.url = webNav.currentURI.spec;
  634.       }
  635.       if( webNav.document.title ) {
  636.          this.post.title = webNav.document.title;
  637.       }
  638.       else {
  639.          this.post.title = this.post.url;
  640.       }
  641.    },
  642.  
  643.    _setSuggestions: function( tags, containerName, maxTags ) {
  644.       if( maxTags == null ) {
  645.          maxTags = tags.length;      // use all available input tags
  646.       }
  647.       if( tags.length > 0 ) {
  648.          var nElts = ( tags.length < maxTags ) ?  tags.length : maxTags;
  649.          var i, elt;
  650.          var container = document.getElementById( containerName );
  651.          var currBox = null, tag;
  652.          var rowStrLen = 0, nInserts = 0;
  653.          for( i = 0; ( nInserts < nElts ) && ( i < tags.length ); ++i ) {
  654.             tag = ( tags.queryElementAt( i, Components.interfaces.nsISupportsString ) ).data;
  655.             if( !this._isSystemTag( tag ) ) {
  656.                if( ( currBox == null ) || ( rowStrLen >= ( this.config.midColMaxChars - 15 ) ) ) {
  657.                   if( currBox != null ) {
  658.                      container.appendChild( currBox );
  659.                   }
  660.                   currBox = document.createElement( "hbox" );
  661.                   rowStrLen = 0;
  662.                }
  663.                elt = this._createTagLabel( tag );
  664.                currBox.appendChild( elt );
  665.                ++nInserts;
  666.                rowStrLen += tag.length;
  667.             }
  668.          }
  669.          if( currBox != null ) {
  670.             container.appendChild( currBox );
  671.             container.hidden = false;
  672.             sizeToContent();
  673.          }
  674.       }
  675.    },
  676.  
  677.    _createTagLabel: function( tag ) {
  678.       var i, elt, newElt = document.createElement( "label" );
  679.       var newEltId = this.config.sgstTagPrefix + this.nSgstTagInserts;
  680.       newElt.setAttribute( "id", newEltId );
  681.       newElt.setAttribute( "value", tag );
  682.       newElt.setAttribute( "class", this.config.class_mousedOut );
  683.       newElt.setAttribute( this.config.attr_selected, "false" );
  684.       newElt.setAttribute( "onclick", "yAddBookMark.tagClick( this );" );
  685.       newElt.setAttribute( "tabindex", "-1" );
  686.       newElt.addEventListener( "mouseover", yAddBookMark.tagMouseOver, false );
  687.       newElt.addEventListener( "mouseout", yAddBookMark.tagMouseOut, false );
  688.       if( this.editOp ) {
  689.          for( i = 0; i < this.post.tags.length; ++i ) {
  690.             if( tag == this.post.tags[ i ] ) {
  691.                newElt.setAttribute( "class", this.config.class_mousedOver );
  692.                newElt.setAttribute( this.config.attr_selected, "true" );
  693.                break;
  694.             }
  695.          }
  696.       }
  697.       ++this.nSgstTagInserts;
  698.       return newElt;
  699.    },
  700.    
  701.    _createRelations: function() {
  702.       var i, j, hash = {}, elt, tag;
  703.       for( i = 0; i < this.nSgstTagInserts; ++i ) {
  704.          elt = document.getElementById( this.config.sgstTagPrefix + i );
  705.          tag = elt.getAttribute( "value" );
  706.          if( !hash[ tag ] ) {
  707.             hash[ tag ] = new Array();
  708.          }
  709.          hash[ tag ].push( elt );
  710.       }
  711.       for( tag in hash ) {
  712.          if( hash[ tag ].length > 1 ) {
  713.             for( i = 0; i < hash[ tag ].length; ++i ) {
  714.                for( j = 0; j < hash[ tag ].length; ++j ) {
  715.                   if( i != j ) {
  716.                      this._addRelative( hash[ tag ][ i ], hash[ tag ][ j ] );
  717.                   }
  718.                }
  719.             }
  720.          }
  721.          hash[ tag ] = null;
  722.       }
  723.    },
  724.  
  725.    _addRelative: function( obj, relative ) {
  726.       var links = obj.getAttribute( this.config.attr_related );
  727.       if( links.length == 0 ) {
  728.          links = relative.getAttribute( "id" );
  729.       }
  730.       else {
  731.          links = links + ',' + relative.getAttribute( "id" );
  732.       }
  733.       obj.setAttribute( this.config.attr_related, links );
  734.    },
  735.    
  736.    tagClick: function( link ) {
  737.       var idx = ybookmarksUtils.containsTag( this.inputTagBox.value, link.value );
  738.       if( idx == -1 ) {
  739.          this._addToUserTags( link.value );
  740.          this._setTagAttribs( link, this.config.class_mousedOver, "true" );
  741.       }
  742.       else {
  743.          this._removeTag( link.value, idx );
  744.          this._setTagAttribs( link, this.config.class_mousedOut, "false" );
  745.       }
  746.       ( document.getElementById( "tb_ybTags" ) ).focus();
  747.    },
  748.  
  749.    _setTagAttribs: function( elt, classVal, selectVal ) {
  750.       elt.setAttribute( "class", classVal );
  751.       elt.setAttribute( this.config.attr_selected, selectVal );
  752.       var relationsStr = elt.getAttribute( this.config.attr_related );
  753.       if( relationsStr.length > 0 ) {
  754.          var relations = relationsStr.split( "," );
  755.          var i, relatedElt;
  756.          for( i = 0; i < relations.length; ++i ) {
  757.             relatedElt = document.getElementById( relations[ i ] );
  758.             relatedElt.setAttribute( "class", classVal );
  759.             relatedElt.setAttribute( this.config.attr_selected, selectVal );
  760.          }
  761.       }
  762.    },
  763.  
  764.    tagMouseOver: function( event ) {
  765.       if( ( event.target.getAttribute( yAddBookMark.config.attr_selected ) == "false" ) && 
  766.          ( event.target.getAttribute( "class" ) != yAddBookMark.config.class_mousedOver ) ) {
  767.             event.target.setAttribute( "class", yAddBookMark.config.class_mousedOver );
  768.       }
  769.    },
  770.  
  771.    tagMouseOut: function( event ) {
  772.       if( ( event.target.getAttribute( yAddBookMark.config.attr_selected ) == "false" ) &&
  773.          ( event.target.getAttribute( "class" ) != yAddBookMark.config.class_mousedOut ) ) {
  774.              event.target.setAttribute( "class", yAddBookMark.config.class_mousedOut );
  775.       }
  776.    },
  777.  
  778.    _querySuggestedTags: function() {
  779.       var cb = {
  780.          onload: function( dataArr ) {
  781.             data = dataArr.queryElementAt( 0, Components.interfaces.nsIPropertyBag );
  782.             var iter = data.enumerator, elt, arr, i, tag;
  783.             while( iter.hasMoreElements() ) {
  784.                elt = iter.getNext().QueryInterface( Components.interfaces.nsIProperty );
  785.                arr = elt.value.QueryInterface( Components.interfaces.nsIArray );
  786.                switch( elt.name ) {
  787.                case "recommended":
  788.                   yAddBookMark._setSuggestions( arr, "hbx_recTags",
  789.                                                 yAddBookMark.config.maxSuggestedTags );
  790.                   break;
  791.                case "network":
  792.                   // UI should include all network tags
  793.                   yAddBookMark._setSuggestions( arr, "hbx_nwTags" );
  794.                   break;
  795.                case "popular":
  796.                   yAddBookMark._setSuggestions( arr, "hbx_popTags",
  797.                                                 yAddBookMark.config.maxSuggestedTags );
  798.                   break;
  799.                }
  800.                // link same tags in different sets
  801.                yAddBookMark._createRelations();
  802.             }
  803.          },
  804.          onerror: function( event ) {
  805.          }
  806.       };
  807.  
  808.       var delStore;
  809.       try {
  810.          delStore = ( Components.classes[ this.kDelContractID ].
  811.                       getService( Components.interfaces.nsISocialStore ) );
  812.      delStore.getSuggestedTags( this.post.url, cb );
  813.       }
  814.       catch( e ) {
  815.          yDebug.print( "exception: " + e, YB_LOG_MESSAGE );
  816.       }
  817.    },
  818.  
  819.    deleteBookMark: function() {
  820.       var func = "yAddBookMark.js: deleteBookMark(): ";
  821.       yDebug.print(func + "this.post.url = \"" + this.post.url + "\"");
  822.       if( this.post.url.length > 0 ) { // Check that URL is valid before trying to delete
  823.          this._getLocalStore();
  824.          this._getSyncService();
  825.          
  826.          yDebug.print(func + "about to delete this.post.url = \"" + this.post.url + "\"");
  827.  
  828.          var promptService = 
  829.              Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
  830.              .getService(Components.interfaces.nsIPromptService);
  831.          var isConfirmed = promptService.confirm(window,
  832.                                                  "Delete bookmark?", 
  833.                                                  "Are you sure you want to delete this bookmark?");
  834.          if (!isConfirmed) {
  835.              return false;
  836.          }
  837.  
  838.          this.localStore.deleteBookmark( this.post.url );
  839.          yDebug.print(func + "deleteBookmark on this.post.url = \"" + this.post.url + "\"");
  840.          var wpost = { url : this.post.url };
  841.          wpost.wrappedJSObject = wpost; 
  842.          yDebug.print(func + "adding txn for deleteBookmark on this.post.url = \"" + this.post.url + "\"");
  843.          this.localStore.addTransaction("deleteBookmark", 0, wpost);            
  844.          yDebug.print(func + "added txn for deleteBookmark on this.post.url = \"" + this.post.url + "\"");
  845.  
  846.          // Notify the sync service that we have a pending transaction to apply to del.icio.us
  847.          var os = Components.classes["@mozilla.org/observer-service;1"]
  848.                   .getService(Components.interfaces.nsIObserverService);
  849.          os.notifyObservers(null, "ybookmark.processTransactions", null);
  850.          os.notifyObservers(null, "ybookmark.bookmarkDeleted", null);
  851.       }
  852.  
  853.       this._removeObservers();
  854.       window.close();
  855.       return true;
  856.    },
  857.  
  858.    _containsShortcut: function(aTags) {
  859.      for (var i=0; i < aTags.length; i++) {
  860.        var tag = aTags[i];
  861.        var index = tag.indexOf(this.config.shortcutTagPref);
  862.        if (index != -1) {
  863.          index += this.config.shortcutTagPref.length;
  864.          return tag.substr(index);
  865.        }
  866.      }
  867.      return "";
  868.    },
  869.    
  870.    _exciseShortcuts: function (aTags) {
  871.       var result = [];
  872.       for (var i=0; i < aTags.length; i++) {
  873.          var tag = aTags[i];
  874.          var index = tag.indexOf(this.config.shortcutTagPref);
  875.          if (index != 0) {
  876.            result.push(tag);
  877.          }
  878.        }
  879.  
  880.        return result;  
  881.    },
  882.     
  883.    saveBookMark: function() {
  884.      
  885.       var notesInput = document.getElementById("tb_yBookmarkNotes");
  886.       var notesCount = document.getElementById("lbl_notesCount");
  887.       var charsRemaining = YB_ADDBOOKMARK_NOTES_MAX_LENGTH - notesInput.textLength;
  888.       if (charsRemaining < 0) {
  889.         try {
  890.           var truncateAutomatically = false;
  891.           try {
  892.             truncateAutomatically = this.prefs.getBoolPref("extensions.ybookmarks@yahoo.bookmark.notes.truncate_automatically");
  893.           } catch (e) { }
  894.            
  895.           if (!truncateAutomatically) {
  896.             var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
  897.                      getService(Components.interfaces.nsIPromptService);
  898.             var title = document.title;
  899.             var text = this.strings.getFormattedString("extensions.ybookmarks.edit_dialog.notes.count.limit", 
  900.                                                        [YB_ADDBOOKMARK_NOTES_MAX_LENGTH])
  901.             var truncate = this.strings.getString("extensions.ybookmarks.edit_dialog.notes.count.limit.truncate");
  902.             var truncateCheck = { value: false };
  903.             
  904.             promptService.alertCheck(this, title, text, truncate, truncateCheck);
  905.             
  906.             if (truncateCheck.value) {
  907.               this.prefs.setBoolPref("extensions.ybookmarks@yahoo.bookmark.notes.truncate_automatically", true);
  908.             } else {
  909.               notesInput.focus();
  910.               return false;
  911.             }
  912.           }
  913.           
  914.           notesInput.value = notesInput.value.substr(0, YB_ADDBOOKMARK_NOTES_MAX_LENGTH);
  915.           
  916.         } catch (e) {
  917.           yDebug.print("yAddBookMark.saveBookMark: error with notes count limit: " + e);
  918.         }
  919.       } 
  920.       
  921.       if( this.blankEntry == true ) {
  922.          this.post.url = ( document.getElementById( "tb_yBookmarkURL" ) ).value;
  923.       }
  924.  
  925.       if( this.post.url.length > 0 ) {
  926.          var elt;
  927.  
  928.          this._getLocalStore();
  929.          this._getSyncService();
  930.          var rv = window.arguments[ 4 ];
  931.          var post;
  932.          
  933.          if( this.editOp ) {
  934.             elt = document.getElementById( "tb_yBookmarkURL" );
  935.             if( this.post.url != elt.value ) {
  936.                this.localStore.deleteBookmark( this.post.url )
  937.                var wpost = { url : this.post.url };
  938.                wpost.wrappedJSObject = wpost; 
  939.                this.localStore.addTransaction("deleteBookmark", 0, wpost);            
  940.                if( elt.value.length == 0 ) {  // user wants to delete the entry?
  941.                   var os = Components.classes["@mozilla.org/observer-service;1"]
  942.                          .getService(Components.interfaces.nsIObserverService);
  943.                   os.notifyObservers(null, "ybookmark.processTransactions", null);
  944.                   this._removeObservers();
  945.                   return;
  946.                }
  947.                this.post.url = elt.value;
  948.                this.editOp = false;
  949.             }
  950.          }
  951.  
  952.          elt = document.getElementById( 'tb_yBookmarkURL' );
  953.          this.post.url = elt.value;
  954.  
  955.          elt = document.getElementById( this.nameInputElt );         
  956.          elt.value = elt.value.substr(0, YB_ADDBOOKMARK_TITLE_MAX_LENGTH);
  957.          this.post.title = elt.value;
  958.  
  959.          elt = document.getElementById( "tb_yBookmarkNotes" );
  960.          if( elt.value.length > 0 ) {
  961.             this.post.notes = elt.value;
  962.          }
  963.  
  964.          elt = document.getElementById( "cb_noShare" );
  965.          this.post.shared = (elt.checked?"false":"true");
  966.  
  967.          elt = document.getElementById( "cb_localOnly" );
  968.          this.post.localOnly = (elt.checked? "true" : "false");         
  969.  
  970.          elt = document.getElementById( "tb_yBookmarkKeyword" );
  971.          this.post.shortcut = elt.value;
  972.    
  973.          yDebug.print ( "IS POST AN RSS => " + this.post.rss );
  974.          this._getPostTags();
  975.          
  976.          
  977.          if (this.editOp) {
  978.              this.post.tags = this._exciseShortcuts(this.post.tags);    
  979.            } else {
  980.              this.post.shortcut =  this.post.shortcut ? this.post.shortcut : this._containsShortcut(this.post.tags);             
  981.              yDebug.print("shortcut found: " + this.post.shortcut);
  982.          }
  983.                   
  984.          if( yDebug.on() ) {
  985.             this._dumpPost();
  986.          }
  987.          
  988.          post = this.post;
  989.          post.wrappedJSObject = post; 
  990.          if( this.editOp ) {
  991.             this.localStore.editBookmark( this.post.url,  this._createBookmarkObject());
  992.             this.localStore.addTransaction("editBookmark", 0, post);            
  993.          }
  994.          else {
  995.             if ( this.post.rss ) {
  996.               this.localStore.addLivemark( this.post.url, this.post.title,
  997.                                            this.post.url, 
  998.                                            this.post.notes,
  999.                                            this.post.tags.length, this.post.tags, 
  1000.                                            this.post.shared,
  1001.                                            this.post.localOnly,                                           
  1002.                                            true );
  1003.  
  1004.             } else {
  1005.               this.localStore.addBookmark( this.post.url, this.post.title,
  1006.                                            this.post.charset, this.post.isWebPanel, this.post.notes, 
  1007.                                            this.post.shortcut,
  1008.                                            this.post.postData,
  1009.                                            this.post.tags.length, this.post.tags, 
  1010.                                            this.post.shared,
  1011.                                            this.post.localOnly,                                           
  1012.                                            true );
  1013.             }
  1014.             this.localStore.addTransaction("addBookmark", 0, post);            
  1015.         }
  1016.  
  1017.         this._updateMicrosummary();
  1018.           
  1019.         var os = Components.classes["@mozilla.org/observer-service;1"]
  1020.                    .getService(Components.interfaces.nsIObserverService);
  1021.         os.notifyObservers(null, "ybookmark.processTransactions", null);
  1022.       }
  1023.  
  1024.       this._removeObservers();
  1025.       window.close();
  1026.    },
  1027.  
  1028.    _updateMicrosummary: function() {
  1029.         // update micro summary too
  1030.         var nameElement = document.getElementById( "menu_yBookmarkName" );
  1031.         var microsummary = null;
  1032.         if ( nameElement.selectedItem ) {
  1033.           microsummary = nameElement.selectedItem.microsummary;
  1034.         }
  1035.         //this.post.microsummary = null;
  1036.         var bookmarkResource = this.localStore.isBookmarked( this.post.url );
  1037.         if ( microsummary ) {
  1038.           this._mss.setMicrosummary ( bookmarkResource, microsummary );
  1039.         } else {
  1040.           if ( this._mss && this._mss.hasMicrosummary (bookmarkResource ) ) {
  1041.             this._mss.removeMicrosummary ( bookmarkResource );
  1042.           }
  1043.         }
  1044.    },
  1045.    
  1046.    _createBookmarkObject: function() {
  1047.       const NSArray = new Components.Constructor( "@mozilla.org/array;1", 
  1048.                                                   Components.interfaces.nsIMutableArray );
  1049.       const NSString = new Components.Constructor( "@mozilla.org/supports-string;1", 
  1050.                                                    Components.interfaces.nsISupportsString );
  1051.       var tags = new NSArray();
  1052.       var i, str;
  1053.       for( i = 0; i < this.post.tags.length; ++i ) {
  1054.          str = new NSString();
  1055.          str.data = this.post.tags[ i ];
  1056.          tags.appendElement( str, false );
  1057.       }
  1058.       return {
  1059.          name: this.post.title,
  1060.          url: this.post.url,
  1061.          description: this.post.notes,
  1062.          tags: tags.QueryInterface( Components.interfaces.nsIArray ),
  1063.          shared: this.post.shared,
  1064.          shortcut: this.post.shortcut,
  1065.          postData: this.post.postData,
  1066.          localOnly : this.post.localOnly         
  1067.       };
  1068.    },
  1069.  
  1070.    _dumpPost: function() {
  1071.       yDebug.print( "url: " + this.post.url );
  1072.       yDebug.print( "title: " + this.post.title );
  1073.       yDebug.print( "notes: " + this.post.notes );
  1074.       yDebug.print( "tags: " + this.post.tags );
  1075.       yDebug.print( "shared: " + this.post.shared );
  1076.       yDebug.print( "localOnly: " + this.post.localOnly );
  1077.       yDebug.print( "shortcut: " + this.post.shortcut );
  1078.    },
  1079.  
  1080.    cancelBookMark: function() {
  1081.      this._removeObservers(); 
  1082.      window.close();
  1083.    },
  1084.  
  1085.    _removeObservers: function() {
  1086.      if ( this._microsummaries ) {
  1087.        try {
  1088.          this._microsummaries.removeObserver( this._observer );
  1089.        } catch ( e ) {
  1090.        }
  1091.      }
  1092.    },
  1093.  
  1094.    _getPostTags: function() {
  1095.       if( this.post.tags == null ) {
  1096.          this.post.tags = new Array();
  1097.       }
  1098.       else {
  1099.          this.post.tags.length = 0;
  1100.       }
  1101.  
  1102.       this.post.tags = this.inputTagBox.value.split( /\s */ );
  1103.       if( this.editOp ) {
  1104.          if( this.post.systemTags ) {
  1105.             var i;
  1106.             for( i = 0; i < this.post.systemTags.length; ++i ) {
  1107.                this.post.tags.push( this.post.systemTags[ i ] );
  1108.             }
  1109.          }
  1110.       } else if( this.post.rss ) {
  1111.          yDebug.print ( "ADDING SYSTEM:RSS TO TAGS" );
  1112.          this.post.tags.push( this.config.rssTag );
  1113.       }
  1114.       
  1115.       if ( this.post.tags.length == 1 && !this.post.tags[0]) {
  1116.         this.post.tags = new Array();
  1117.         this.post.tags.push( this.config.emptyTag );
  1118.       }
  1119.       
  1120.    },
  1121.  
  1122.    _removeTag: function( tag, idx ) {
  1123.       var str = "";
  1124.       if( tag.length != this.inputTagBox.value.length ) {
  1125.          if( idx == 0 ) {
  1126.             str = this.inputTagBox.value.substr( tag.length + 1 );
  1127.          }
  1128.          else {
  1129.             str = this.inputTagBox.value.substr( 0, idx - 1 ) + 
  1130.                this.inputTagBox.value.substr( idx + tag.length );
  1131.          }
  1132.       }
  1133.       this.inputTagBox.value = str;      
  1134.    },
  1135.  
  1136.    _addToUserTags: function( tag ) {
  1137.       if( this.inputTagBox.value.length == 0 ) {
  1138.          this.inputTagBox.value = tag;
  1139.       }
  1140.       else {
  1141.          if (this.inputTagBox.value.charAt(this.inputTagBox.value.length-1) == " ")
  1142.            this.inputTagBox.value += tag;
  1143.          else 
  1144.            this.inputTagBox.value += " " + tag;
  1145.       }
  1146.       this.inputTagBox.value += " ";
  1147.    },
  1148.  
  1149.    _checkAddMechPref: function() {
  1150.       var prefVal = 1;
  1151.       try {
  1152.      prefVal = this.prefs.getIntPref( "extensions.ybookmarks@yahoo.addmechanism" );
  1153.       }
  1154.       catch( e ) { }
  1155.       return prefVal;
  1156.    },
  1157.    
  1158.    _traditionalAdd: function() {
  1159.  
  1160.       yDebug.print( "Ok, need to do traditional add for: url " + this.post.url +
  1161.             " and title: " + this.post.title );
  1162.  
  1163.       var bundleService = 
  1164.             Components.classes[ "@mozilla.org/intl/stringbundle;1" ].getService( 
  1165.                 Components.interfaces.nsIStringBundleService );
  1166.       var bundle = 
  1167.             bundleService.createBundle( "chrome://ybookmarks/locale/ybookmarks.properties" );
  1168.  
  1169.       var url;
  1170.       
  1171.       if (this.post.rss) {
  1172.         url = deliciousService.getPostRssUrl(this.post.url, this.post.title,
  1173.             this.post.notes, this.config.rssTag);
  1174.       } else {
  1175.         url = deliciousService.getPostUrl(this.post.url, this.post.title,
  1176.             this.post.notes);
  1177.       }
  1178.       yDebug.print( "Going to open url: " + url, YB_LOG_MESSAGE ); 
  1179.       this._openDelWindow( url, 700, 400 );
  1180.    },
  1181.  
  1182.    _openDelWindow: function( url, width, height ){
  1183.       //make it center  
  1184.       var left = parseInt( ( screen.availWidth / 2 ) - ( width / 2 ) ); 
  1185.       var top  = parseInt( ( screen.availHeight / 2 ) - ( height / 2 ) );
  1186.       var props = "width=" + width + ",height=" + height + ",left=" + left + ",top=" + top +
  1187.          ",menubar=0,toolbar=0,scrollbars=1,location=0,status=1,resizable=1" 
  1188.       var newWindow = window.open( url, "", props );
  1189.       setTimeout( "yAddBookMark.delWindowLoaded()", 0 );
  1190.    },
  1191.    
  1192.    delWindowLoaded: function( event ) {
  1193.       var wm = Components.classes[ "@mozilla.org/appshell/window-mediator;1" ]
  1194.                               .getService( Components.interfaces.nsIWindowMediator );
  1195.       var ref = wm.getMostRecentWindow( "navigator:browser" );
  1196.       ref.focus();
  1197.       ref.addEventListener( "unload", yAddBookMark.delWindowClosed, false );
  1198.    },
  1199.  
  1200.    delWindowClosed: function( event ) {
  1201.       var syncService = ( Components.classes[this.kSyncServiceContractID].
  1202.                                  getService(Components.interfaces.nsIYBookmarkSyncService) );
  1203.       syncService.sync(false);
  1204.    },
  1205.  
  1206.    /** 
  1207.     * Clone of addBookmarkForBrowser from firefox source
  1208.     * This is necessary to override the bookmarking functionality
  1209.     */
  1210.    addBookmarkForTabBrowser: function( aTabBrowser ) {
  1211.  
  1212.      var webNav = aTabBrowser.webNavigation;
  1213.      var url = webNav.currentURI.spec;
  1214.      var title, description, charset;
  1215.      try {
  1216.        var doc = webNav.document;
  1217.        title = doc.title || url;
  1218.        charset = doc.characterSet;
  1219.        description = ybookmarksUtils.getDescriptionFromDocument( doc );
  1220.      } catch ( e ) {
  1221.        title = url;
  1222.      }
  1223.  
  1224.      this.open( url, title, charset, false, description );
  1225.    },
  1226.  
  1227.    addLiveBookmark: function(event) {
  1228.      var url = event.target.getAttribute('feed');
  1229.      var doc = gBrowser.selectedBrowser.contentDocument;
  1230.      var title = doc.title;
  1231.      var description = ybookmarksUtils.getDescriptionFromDocument(doc);
  1232.      event.stopPropagation();
  1233.      this.open(doc.baseURI, title, "", false, description, url);
  1234.    },
  1235.  
  1236.     /* copy of FF FeedHandler.buildFeedList. Required to add delicious options for adding livemarks */
  1237.    ybuildFeedList: function(arg) {
  1238.      var menuPopup = null;
  1239.      var addDeliciousOptions = true;
  1240.      var ff1_5 = false;
  1241.      if (arg instanceof MouseEvent) {
  1242.         menuPopup = arg.target;
  1243.         ff1_5 = true;
  1244.      } else {
  1245.         menuPopup = arg;
  1246.      }
  1247.      var parent = menuPopup.parentNode;
  1248.      if (parent) {
  1249.         if (parent.id == "subscribeToPageMenupopup") {
  1250.             addDeliciousOptions = false;
  1251.         }
  1252.      }
  1253.      var feeds = gBrowser.selectedBrowser.feeds;
  1254.      if (feeds == null) {
  1255.        menuPopup.parentNode.removeAttribute("open");
  1256.        return false;
  1257.      }
  1258.  
  1259.      while (menuPopup.firstChild)
  1260.        menuPopup.removeChild(menuPopup.firstChild);
  1261.     
  1262.         /**
  1263.          * Attempt to generate a list of unique feeds from the list of feeds
  1264.          * supplied by the web page. It is fairly common for a site to supply
  1265.          * feeds in multiple formats but with divergent |title| attributes so
  1266.          * we need to make a rough pass at trying to not show a menu when there
  1267.          * is in fact only one feed. If this is the case, by default select
  1268.          * the ATOM feed if one is supplied, otherwise pick the first one. 
  1269.          * @param   feeds
  1270.          *          An array of Feed info JS Objects representing the list of
  1271.          *          feeds advertised by the web page
  1272.          * @returns An array of what should be mostly unique feeds. 
  1273.          */
  1274.         function harvestFeeds(feeds) {
  1275.           var feedHash = { };
  1276.           for (var i = 0; i < feeds.length; ++i) {
  1277.             var feed = feeds[i];
  1278.             if (!(feed.type in feedHash))
  1279.               feedHash[feed.type] = [];
  1280.             feedHash[feed.type].push(feed);
  1281.           }
  1282.           var mismatch = false;
  1283.           var count = 0;
  1284.           var defaultType = null;
  1285.           for (var type in feedHash) {
  1286.             // The default type is whichever is listed first on the web page.
  1287.             // Nothing fancy, just something that works.
  1288.             if (!defaultType) {
  1289.               defaultType = type;
  1290.               count = feedHash[type].length;
  1291.             }
  1292.             if (feedHash[type].length != count) {
  1293.               mismatch = true;
  1294.               break;
  1295.             }
  1296.             count = feedHash[type].length;
  1297.           }
  1298.           // There are more feeds of one type than another - this implies the
  1299.           // content developer is supplying multiple channels, let's not do 
  1300.           // anything fancier than this and just return the full set. 
  1301.           if (mismatch)
  1302.             return feeds;
  1303.  
  1304.           // Look for an atom feed by default, fall back to whichever was listed
  1305.           // first if there is no atom feed supplied. 
  1306.           const ATOMTYPE = "application/atom+xml";
  1307.           return ATOMTYPE in feedHash ? feedHash[ATOMTYPE] : feedHash[defaultType];
  1308.         }
  1309.  
  1310.       var feeds = harvestFeeds(feeds);
  1311.       var askForReader = true;
  1312.       try {
  1313.         var feedHandler = this.prefs.getCharPref("browser.feeds.handler");
  1314.         askForReader = (feedHandler == "ask");
  1315.       } catch ( e ) { }
  1316.  
  1317.       if ((!askForReader) && (feeds.length == 1)) {      
  1318.         return false;
  1319.       }
  1320.       if (parent.id == "feed-button") {
  1321.         parent.removeAttribute("feed");
  1322.       }
  1323.             
  1324.       var hideFFBMMenu = false;
  1325.       try {
  1326.         hideFFBMMenu = this.prefs.getBoolPref("extensions.ybookmarks@yahoo.original.ui.hide");
  1327.       } catch ( e ) { }
  1328.  
  1329.      var strings = document.getElementById("ybookmarks-strings");
  1330.  
  1331.      // Build the menu showing the available feed choices for viewing. 
  1332.      for (var i = 0; i < feeds.length; ++i) {
  1333.        var feedInfo = feeds[i];
  1334.        var baseTitle = feedInfo.title || feedInfo.href;
  1335.  
  1336.        if ((!ff1_5) || ((ff1_5) && (hideFFBMMenu == false))) {
  1337.            var menuItem = document.createElement("menuitem");
  1338.            var labelStr;
  1339.            try {
  1340.              labelStr = gNavigatorBundle.getFormattedString("feedShowFeed",[baseTitle]);
  1341.            } catch(e) {
  1342.              labelStr = gNavigatorBundle.getFormattedString("feedShowFeedNew",[baseTitle]);
  1343.            }           
  1344.            menuItem.setAttribute("label", labelStr);
  1345.            menuItem.setAttribute("feed", feedInfo.href);
  1346.            menuItem.setAttribute("tooltiptext", feedInfo.href);
  1347.            menuPopup.appendChild(menuItem);
  1348.        }
  1349.        if ((askForReader) && (addDeliciousOptions == true)) {
  1350.            var menuItem = document.createElement("menuitem");
  1351.            var labelStr = strings.getFormattedString("extensions.ybookmarks.add.livemark", [baseTitle]);
  1352.            menuItem.setAttribute("label", labelStr);
  1353.            menuItem.setAttribute("feed", feedInfo.href);
  1354.            menuItem.setAttribute("tooltiptext", feedInfo.href);
  1355.            menuItem.setAttribute("oncommand", "yAddBookMark.addLiveBookmark(event)");       
  1356.            menuPopup.appendChild(menuItem);
  1357.        }       
  1358.      }
  1359.      return true;
  1360.    },
  1361.  
  1362.    resolveKeyword: function(aURL, aPostDataRef) {
  1363.        var keyword = aURL.toLowerCase();
  1364.        var ds = this.localStore.getDataSource();       
  1365.        if(!RDF) {
  1366.           //required for FF3
  1367.           var RDF = Components.classes['@mozilla.org/rdf/rdf-service;1'].getService(Components.interfaces.nsIRDFService);          
  1368.        }
  1369.        var source = ds.GetSource(RDF.GetResource("http://home.netscape.com/NC-rdf#ShortcutURL"),
  1370.             RDF.GetLiteral(keyword), true);
  1371.        if (source) {
  1372.             var url = ds.GetTarget(source, 
  1373.                 RDF.GetResource("http://home.netscape.com/NC-rdf#URL"), true);
  1374.             if (url) {
  1375.                 var node = ds.GetTarget(source, 
  1376.                     RDF.GetResource("http://home.netscape.com/NC-rdf#PostData"), true);
  1377.                 if (node) {
  1378.                     var postDataString = node.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
  1379.                     if (postDataString.length > 0) {
  1380.                         aPostDataRef.value = postDataString;
  1381.                     }
  1382.                 }
  1383.             
  1384.                 return url.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
  1385.             }
  1386.        }
  1387.        return null;
  1388.    },
  1389.  
  1390.    getShortcutOrURI: function(aURL, aPostDataRef) {
  1391.       try {      
  1392.         this._getLocalStore();
  1393.         var shortcutURL = this.resolveKeyword(aURL, aPostDataRef);
  1394.         if (!shortcutURL) {
  1395.           var aOffset = aURL.indexOf(" ");
  1396.           if (aOffset > 0) {
  1397.             var cmd = aURL.substr(0, aOffset);
  1398.             var text = aURL.substr(aOffset+1);
  1399.             shortcutURL = this.resolveKeyword(cmd, aPostDataRef);
  1400.             if (shortcutURL && text) {
  1401.               var encodedText = null; 
  1402.               var charset = "";
  1403.               const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/; 
  1404.               var matches = shortcutURL.match(re);
  1405.               if (matches) {
  1406.                  shortcutURL = matches[1];
  1407.                  charset = matches[2];
  1408.               }
  1409.               else if (/%s/.test(shortcutURL) || 
  1410.                        (aPostDataRef && /%s/.test(aPostDataRef.value))) {
  1411.                 try {
  1412.                   charset = this.getLastCharset(shortcutURL);
  1413.                 } catch (ex) {
  1414.                 }
  1415.               }
  1416.  
  1417.               if (charset)
  1418.                 encodedText = escape(convertFromUnicode(charset, text)); 
  1419.               else  // default case: charset=UTF-8
  1420.                 encodedText = encodeURIComponent(text);
  1421.  
  1422.               if (aPostDataRef && aPostDataRef.value) {
  1423.                 // XXXben - currently we only support "application/x-www-form-urlencoded"
  1424.                 //          enctypes.
  1425.                 aPostDataRef.value = unescape(aPostDataRef.value);
  1426.                 if (aPostDataRef.value.match(/%[sS]/)) {
  1427.                   aPostDataRef.value = getPostDataStream(aPostDataRef.value,
  1428.                                                          text, encodedText,
  1429.                                                          "application/x-www-form-urlencoded");
  1430.                 }
  1431.                 else {
  1432.                   shortcutURL = null;
  1433.                   aPostDataRef.value = null;
  1434.                 }
  1435.               }
  1436.               else {
  1437.                 
  1438.                 if (/%[sS]/.test(shortcutURL))
  1439.                   shortcutURL = shortcutURL.replace(/%s/g, encodedText)
  1440.                                            .replace(/%S/g, text);
  1441.                 else {
  1442.                   // don't do any substitution, but still return the expanded url
  1443.                 } 
  1444.               }
  1445.             }
  1446.           }
  1447.         }
  1448.                 
  1449.         var origURL = this.originalGetShortcutOrURI(aURL, aPostDataRef);
  1450.         
  1451.           if (shortcutURL && origURL != aURL) {
  1452.               var warnCheck = this.prefs.getBoolPref("extensions.ybookmarks@yahoo.original.keyword.conflicts.warn");
  1453.               if (warnCheck) {
  1454.               var stringService = Components.classes["@mozilla.org/intl/stringbundle;1"].
  1455.                               getService(Components.interfaces.nsIStringBundleService);
  1456.               var strings = stringService.createBundle("chrome://ybookmarks/locale/ybookmarks.properties");
  1457.           
  1458.                 var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
  1459.                        getService(Components.interfaces.nsIPromptService);
  1460.                 var text = strings.GetStringFromName("extensions.ybookmarks.original.keyword.conflicts.text");
  1461.                 var warn = strings.GetStringFromName("extensions.ybookmarks.original.keyword.conflicts.warn");
  1462.                 var warnCheck = { value: true };
  1463.             
  1464.               promptService.alertCheck(window, "Delicious", text, warn, warnCheck);
  1465.   
  1466.                 if (!warnCheck.value) {
  1467.                   this.prefs.setBoolPref("extensions.ybookmarks@yahoo.original.keyword.conflicts.warn", false);
  1468.                 }
  1469.           
  1470.               } 
  1471.           }
  1472.         
  1473.         if (shortcutURL && origURL == aURL) {
  1474.           return shortcutURL;
  1475.         } else {
  1476.           yDebug.print("overridden getShortcutOrURI... Delegating");
  1477.           return origURL;
  1478.         }
  1479.       } catch (e) {
  1480.         yDebug.print("getShortcutOrURI(): " + e, YB_LOG_MESSAGE);
  1481.         try {
  1482.           return this.originalGetShortcutOrURI(aURL, aPostDataRef);
  1483.         } catch (e) {
  1484.           yDebug.print("getShortcutOrURI(): Even worse! error with this.originalGetShortcutOrURI(): " + e, YB_LOG_MESSAGE);
  1485.           return aURL;
  1486.         }
  1487.       }
  1488.   
  1489.    },
  1490.  
  1491.    addHooks: function() {
  1492.      yDebug.print("Adding hooks.", YB_LOG_MESSAGE);
  1493.      try {
  1494.      // put in our shortcut url handler
  1495.       var topWindow = ybookmark_Utils._getTopWindow();
  1496.  
  1497.       // the mac seems to add the hooks in weird cases. For instance, if you bring up the
  1498.       // preferences window, it'll break the addressbar.  This is probably due
  1499.       // to the overlay being included in every new window ala this in chrome.manifest
  1500.       // overlay chrome://browser/content/macBrowserOverlay.xul chrome://ybookmarks/content/ybookmarksOverlay.xul
  1501.       var addHooks = true;
  1502.       if (ybookmarksUtils.getPlatform() == YB_PLATFORM_MAC) {  
  1503.         if ( !(topWindow &&  window.content) ) {      
  1504.           // topWindow.browserDOMWindow && <-- took out this condition.  fix for bug 1071605
  1505.           addHooks = false;
  1506.         }
  1507.       } 
  1508.       if (!addHooks) {
  1509.         return;
  1510.       }
  1511.       
  1512.       
  1513.       if (topWindow) {
  1514.         yDebug.print("Adding Livemark Hook.", YB_LOG_MESSAGE);
  1515.         topWindow.FeedHandler.buildFeedList = 
  1516.               function(event) { return yAddBookMark.ybuildFeedList(event); };
  1517.       }
  1518.  
  1519.       if (yAddBookMark.originalGetShortcutOrURI == null) {
  1520.         yDebug.print("Adding ShortuctURI Hook.", YB_LOG_MESSAGE);
  1521.       
  1522.         yAddBookMark.originalGetShortcutOrURI = topWindow.getShortcutOrURI;
  1523.         topWindow.getShortcutOrURI = function(aURL, aPostDataRef) {
  1524.               return yAddBookMark.getShortcutOrURI(aURL, aPostDataRef);
  1525.         };
  1526.       }
  1527. /*      var hideFFBMUI = false;
  1528.       var remapShortcutKeys = false;
  1529.       try {
  1530.         hideFFBMUI = this.prefs.getBoolPref("extensions.ybookmarks@yahoo.original.ui.hide");
  1531.         remapShortcutKeys = this.prefs.getBoolPref("extensions.ybookmarks@yahoo.original.keybindings.remap");
  1532.       } catch ( e ) { }
  1533.       
  1534.       if (hideFFBMUI || remapShortcutKeys) {
  1535.           var docelem = document.getElementById("addBookmarkAsKb");
  1536.           docelem.setAttribute("command", "cmd_yb_bookmark_this_page");
  1537.           docelem = document.getElementById("viewBookmarksSidebarKb");
  1538.           docelem.setAttribute("command", "viewYBookmarksSidebar");
  1539.       }      
  1540. */  
  1541.     } catch (e) {
  1542.       yDebug.print("yAddBookmarks.addHooks():" + e, YB_LOG_MESSAGE);
  1543.     }
  1544.     },
  1545.    
  1546.    // This function has code copied from browser.js. Alas, there seems to be no
  1547.    // cleaner way to do this. The browser code is hardcoded to open it's own
  1548.    // add bookmark dialog. The code here is the same except for the last part
  1549.    // (where this function opens our dialog).
  1550.    createSearchKeywordBookmark: function () {
  1551.       yDebug.print( "yAddBookMark.createSearchKeywordBookmark called!" );
  1552.       var node = document.popupNode;
  1553.       var ioService = Components.classes["@mozilla.org/network/io-service;1"]
  1554.       .getService(Components.interfaces.nsIIOService);
  1555.       var uri = ioService.newURI(node.ownerDocument.URL, node.ownerDocument.characterSet, null);
  1556.  
  1557.       var keywordURL = ioService.newURI(node.form.getAttribute("action"), node.ownerDocument.characterSet, uri);
  1558.       var spec = keywordURL.spec;
  1559.       var postData = "";
  1560.       var i, e;
  1561.  
  1562.       if (node.form.method.toUpperCase() == "POST" &&
  1563.           (node.form.enctype == "application/x-www-form-urlencoded" || node.form.enctype == "")) {
  1564.          for (i=0; i < node.form.elements.length; ++i) {
  1565.             e = node.form.elements[i];
  1566.             if (e.type) {
  1567.                if (e.type.toLowerCase() == "text" || e.type.toLowerCase() == "hidden" ||
  1568.                    e instanceof HTMLTextAreaElement)
  1569.                   postData += escape(e.name + "=" + (e == node ? "%s" : e.value)) + "&";
  1570.                else if (e instanceof HTMLSelectElement && e.selectedIndex >= 0)
  1571.                postData += escape(e.name + "=" + e.options[e.selectedIndex].value) + "&";
  1572.                else if ((e.type.toLowerCase() == "checkbox" ||
  1573.                  e.type.toLowerCase() == "radio") && e.checked)
  1574.            postData += escape(e.name + "=" + e.value) + "&";
  1575.             }
  1576.          }
  1577.       }
  1578.       else {
  1579.          spec += "?" + escape(node.name) + "=%s";
  1580.          for (i=0; i < node.form.elements.length; ++i) {
  1581.             e = node.form.elements[i];
  1582.             if (e == node) { // avoid duplication of the target field value, which was populated above. 
  1583.                continue;
  1584.             }
  1585.             if (e.type) { 
  1586.                if (e.type.toLowerCase() == "text" || e.type.toLowerCase() == "hidden" ||
  1587.                    e instanceof HTMLTextAreaElement)
  1588.                   spec += "&" + escape(e.name) + "=" + escape(e.value);
  1589.                else if (e instanceof HTMLSelectElement && e.selectedIndex >= 0)
  1590.                spec += "&" + escape(e.name) + "=" + escape(e.options[e.selectedIndex].value);
  1591.                else if ((e.type.toLowerCase() == "checkbox" ||
  1592.                  e.type.toLowerCase() == "radio") && e.checked)
  1593.            spec += "&" + escape(e.name) + "=" + escape(e.value);
  1594.             }
  1595.          }
  1596.       }
  1597.       this.open( spec, "", null, null, null, null, false, postData, true );
  1598.    },
  1599.  
  1600.    /**
  1601.     * Get the top most browser window
  1602.     **/
  1603.    _getTopWindow : function() {
  1604.      var windowManager = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService();
  1605.      var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
  1606.      var topWindow = windowManagerInterface.getMostRecentWindow( "navigator:browser" );
  1607.  
  1608.      return topWindow;
  1609.    },
  1610.  
  1611.    bookmarkTransactionsObserver : {
  1612.      
  1613.      observe: function(subject, topic, data) {
  1614.      
  1615.        if (topic == "ybookmark.processTransactions") {
  1616.          var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
  1617.                  getService(Components.interfaces.nsIWindowMediator);
  1618.          var recentWindow = wm.getMostRecentWindow("navigator:browser");
  1619.          if (recentWindow != window) {
  1620.            return;
  1621.          }
  1622.            
  1623.          window.setTimeout(yAddBookMark.processTransactions, 0);
  1624.        }
  1625.      }
  1626.    },
  1627.    
  1628.    processTransactions : function() {
  1629.       
  1630.       if(this != yAddBookMark) {
  1631.         yAddBookMark.processTransactions();
  1632.         return;
  1633.       }
  1634.       
  1635.       this._getSyncService();
  1636.       this.syncService.processTransactions();
  1637.    },
  1638.    
  1639.    saveSearchString: function () {
  1640.         var temp = this.inputTagBox.value.split(" ");
  1641.         temp.pop();
  1642.         this.inputTagBox.setAttribute("savedSearchString", temp.join(" "));
  1643.    },
  1644.    
  1645.    prependSavedSearchString: function () {
  1646.        var tmp = this.inputTagBox.getAttribute("savedSearchString");
  1647.        
  1648.        if(tmp) tmp = tmp + " ";
  1649.        
  1650.        this.inputTagBox.value =  tmp + this.inputTagBox.value;
  1651.    }
  1652.    
  1653. };
  1654.  
  1655.